package replay

import (
	"encoding/binary"
	"os"
	"time"
)

// Recorder 追加写原始数据，带时间戳.
type Recorder struct {
	f              *os.File
	protocolPrefix []byte // 协议前缀
}

// NewRecorder 创建或打开文件用于追加记录.
func NewRecorder(fileName string) (*Recorder, error) {
	f, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return nil, err
	}
	return &Recorder{f: f}, nil
}

// SetProtocolPrefix 设置协议前缀
func (r *Recorder) SetProtocolPrefix(prefix []byte) {
	r.protocolPrefix = make([]byte, len(prefix))
	copy(r.protocolPrefix, prefix)
}

func (r *Recorder) DirectWrite(data []byte) error {
	_, err := r.f.Write(data)
	return err
}

// Record 立即写入一条数据.
func (r *Recorder) Write(data []byte) error {
	return r.WriteWithNowTime(time.Now(), data)
}

// Record 立即写入一条数据.
func (r *Recorder) WriteWithNowTime(nowTime time.Time, data []byte) error {
	// 如果设置了协议前缀，先写入前缀
	if len(r.protocolPrefix) > 0 {
		if _, err := r.f.Write(r.protocolPrefix); err != nil {
			return err
		}
	}

	if err := binary.Write(r.f, binary.LittleEndian, nowTime.UnixNano()); err != nil {
		return err
	}
	if err := binary.Write(r.f, binary.LittleEndian, uint32(len(data))); err != nil {
		return err
	}
	_, err := r.f.Write(data)
	return err
}

// Close 关闭文件.
func (r *Recorder) Close() error { return r.f.Close() }
